#pragma once

#include "ThreadPool/Log.hpp"
#include "./ThreadPool/Task.hpp"
#include "./ThreadPool/ThreadPool.hpp"
#include <iostream>
#include <unistd.h>
#include <string>
#include <cerrno>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <unistd.h>

const int g_size = 1024;

static void server(int serverSock, struct sockaddr_in sock_cli)
{
    char buffer[g_size];  // 存储读取数据的缓冲区

    // std::cout << "read" << std::endl;

    while(true)
    {
        ssize_t n = recv(serverSock, buffer, g_size - 1, 0);   // 读取数据
        if(n > 0)
        {
            buffer[n] = '\0';

            uint16_t cli_port = ntohs(sock_cli.sin_port);
            char cli_addr[20]; // 地址
            memset(cli_addr, 0, sizeof(cli_addr));
            // socklen_t len = sizeof(sock_cli.sin_addr);
            inet_ntop(AF_INET, &sock_cli.sin_addr, cli_addr, sizeof(cli_addr));
            printf("[%s-%d] %s\n", cli_addr, cli_port, buffer);

            // 发回客户端
            send(serverSock, buffer, strlen(buffer), 0);
        }
        else if(n == 0)
        {
            logMessage(DEBUG, "对端关闭，读取结束！\n");
            break;
        }
        else  // n < 0
        {
            logMessage(ERROR, "读取失败！\n");
            break;
        }
    }

    close(serverSock);
}

class TcpServer
{
public:
    TcpServer(uint16_t port, const std::string &ip = "")
        : _port(port), _ip(ip), _listenSock(-1)
    { 
    }

    // 服务器初始化
    void init()
    {
        // 1. 创建网络套接字
        _listenSock = socket(AF_INET, SOCK_STREAM, 0);
        if (_listenSock < 0) // 创建socket失败
        {
            logMessage(FATAL, "socket error, %d:%s\n", errno, strerror(errno));
            exit(2);
        }
        logMessage(NORMAL, "socket success, _listenSock:%d\n", _listenSock);

        // 2. 绑定端口号
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));

        local.sin_family = AF_INET;                                                // 设置网络协议族
        local.sin_addr.s_addr = _ip.empty() ? INADDR_ANY : inet_addr(_ip.c_str()); // 本地格式地址转为网络格式
        local.sin_port = htons(_port);                                             // 本地格式端口号转为网络格式

        if (bind(_listenSock, (const sockaddr *)&local, sizeof(local)) < 0)
        {
            logMessage(FATAL, "bind error, %d:%s\n", errno, strerror(errno));
            exit(3);
        }
        logMessage(NORMAL, "bind success, %s:%d\n", _ip.c_str(), _port);

        // 3. 设置监听状态
        if (listen(_listenSock, _backlog) < 0)
        {
            logMessage(FATAL, "listen error, %d:%s\n", errno, strerror(errno));
            exit(4);
        }
        logMessage(NORMAL, "listen success\n");
        logMessage(NORMAL, "Server Init Success!\n");
    }

    // 运行服务器
    void start()
    {
        _thread_pool.run();
        while (true)
        {
            // 接受客户端的链接请求
            struct sockaddr_in sock_cli;
            memset(&sock_cli, 0, sizeof(sock_cli));
            socklen_t len = sizeof(sock_cli);

            int serverSock = accept(_listenSock, (struct sockaddr *)&sock_cli, &len);
            if (serverSock < 0) // 接受客户端请求失败
            {
                logMessage(ERROR, "accept error, %d:%s\n", errno, strerror(errno));
                continue;
            }

            uint16_t cli_port = ntohs(sock_cli.sin_port);
            char cli_addr[20]; // 地址
            memset(cli_addr, 0, sizeof(cli_addr));
            inet_ntop(AF_INET, &sock_cli.sin_addr, cli_addr, len);
            cli_addr[strlen(cli_addr)] = '\0';
            logMessage(NORMAL, "accept success, serverSock:%d [%s-%d]\n", serverSock, cli_addr, cli_port);

            Task task(server, serverSock, sock_cli);   // 创建网络读取任务
            _thread_pool.push_task(task);
            logMessage(NORMAL, "push_task success!\n");

            // // 多进程接受客户端信息
            // pid_t id = fork();
            // if (id == 0)
            // {
            //     if (fork() > 0)
            //         exit(0); // 子进程退出

            //     // 子进程的子进程（孙子进程）此时变为孤儿进程
            //     // 由1号进程领养，OS自动回收进程
            //     server(serverSock, sock_cli);
            //     exit(0);
            // }

            // waitpid(id, nullptr, 0);
            // close(serverSock);
        }
    }

    // 析构函数
    ~TcpServer()
    {
        if (_listenSock >= 0)
        {
            close(_listenSock);
        }
    }

private:
    uint16_t _port;  // 端口号
    std::string _ip; // 本地ip
    int _listenSock; // socket文件描述符
    ThreadPool<Task> _thread_pool;  // 线程池

    static const int _backlog = 20;
};
